// src/hooks/useServer.ts
import { ref, provide, inject } from 'vue';
import { io } from 'socket.io-client';
import { useUserStore } from '@/stores/userStore';
import { useRouter } from 'vue-router';

interface Message {
  id: string
  sender: string
  type: 'text' | 'functionTest'
  content: {text?:string, end?:boolean, data?:any, role?:string}
  timestamp: number
  route?: string
}
const randomId = Math.random().toString(36).substring(2, 9);
const WebSocketSymbol = Symbol('WebSocketConnection');

export const useServer = () => {
  const serverUrl = ref('http://localhost:5000/api');
  const wsserverUrl = ref('ws://localhost:5000');
  //   const serverUrl = ref('http://asengine.net/api');
  // const wsserverUrl = ref('ws://asengine.net');
  const router = useRouter();
  const userStore = useUserStore();
  
  // 使用 Map 来存储不同项目的 WebSocket 连接
  const wsConnections = ref<Map<string, ReturnType<typeof io>>>(new Map());
  const currentProjectToken = ref<string>('');
  const isConnected = ref<boolean>(false);
  const messages = ref<Message[]>([]);
  const messageRoute = ref<string>("");
  const audioRoute = ref<string>("");
  const imageRoute = ref<string>("");
  const mediaRecorder = ref<MediaRecorder | null>(null);
  const audioChunks = ref<Blob[]>([]);
  const isRecording = ref<boolean>(false);

  // 获取当前项目的 WebSocket 连接
  const getCurrentWs = () => {
    return currentProjectToken.value ? wsConnections.value.get(currentProjectToken.value) : null;
  };

  // 发送 GET 请求
  const get = async (endpoint: string, params?: Record<string, any>,testUrl?:string) => {
    try {
      const queryParams = params ? `?${new URLSearchParams(params).toString()}` : '';
      let url;
      if(testUrl){
        url=`${testUrl}/${endpoint}${queryParams}`
      }else{
        url=`${serverUrl.value}/${endpoint}${queryParams}`
      }
      const response = await fetch(url, {
        method: 'GET',
        headers: {
          'Content-Type': 'application/json',
        },
      });
      if (!response.ok) throw new Error(`Error: ${response.status}`);
      return await response.json();
    } catch (error) {
      console.error('GET Request Error:', error);
      throw error;
    }
  };

  // 发送 POST 请求
  const post = async (endpoint: string, data: Record<string, any>,testUrl?:string) => {
    // 对于登录和注册请求，跳过用户验证
    const isAuthEndpoint = endpoint === 'login' || endpoint === 'register'||endpoint==='sendEmailCode'||endpoint==='remote_login';


    // 检查用户是否登录（非登录/注册请求时）
    if (!isAuthEndpoint && !userStore.isLoggedIn) {
      router.push('/login');
      throw new Error('User not logged in');
    }
    let url;
    if(testUrl){
      url=`${testUrl}/${endpoint}`
    }else{
      url=`${serverUrl.value}/${endpoint}`
    }
    try {
      const response = await fetch(url, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'Accept': 'application/json',
        },
        body: JSON.stringify(
          isAuthEndpoint ? data : {
            ...data,
            userID: userStore.currentUser
          }
        ),
      });
      
      if (!response.ok) {
        // 如果是未授权错误或会话过期，跳转到登录页面
        if (response.status === 401 || response.status === 403) {
          userStore.logout();  // 清除本地登录状态
          router.push('/login');
          throw new Error('Session expired or unauthorized');
        }
        throw new Error(`Error: ${response.status}`);
      }
      
      return await response.json();
    } catch (error: any) {  // 明确指定 error 类型为 any
      console.error('POST Request Error:', error);
      // 如果错误消息包含特定关键词，也跳转到登录页面
      if (typeof error.message === 'string' && (
          error.message.toLowerCase().includes('unauthorized') || 
          error.message.toLowerCase().includes('unauthenticated') ||
          error.message.toLowerCase().includes('session'))) {
        userStore.logout();  // 清除本地登录状态
        router.push('/login');
      }
      throw error;
    }
  };

const postFile = async (endpoint: string, formData: FormData,testUrl?:string) => {
  try {
    let url;
    if(testUrl){
      url=`${testUrl}/${endpoint}`
    }else{
      url=`${serverUrl.value}/${endpoint}`
    }
    const response = await fetch(url, {
      method: "POST",
      body: formData, // 只支持 FormData
      headers: {
        'Accept': 'application/json',//不需要手动设置multipart/form-data让浏览器自己生成boundary
      },
    });
    const result = await response.json();
    return result;
  } catch (error) {
    console.error( error);
  }
};

  const postWithCallback = async (
    endpoint: string,
    data: Record<string, any>,
    callback: (response: any) => void,
    testUrl?:string
  ) => {
    try {
      const response = await post(endpoint, data,testUrl);
      callback(response); // 调用回调函数并传递响应数据
      return response; // 返回响应数据（可选）
    } catch (error) {
      console.error('POST Request with Callback Error:', error);
      throw error;
    }
  };

  // 连接到 Message WebSocket 服务器
  const connectWebSocket = (token: string) => {
    if (wsConnections.value.has(token)) {
      const existingWs = wsConnections.value.get(token);
      if (existingWs) {
        existingWs.close();
      }
    }

    // 创建新的连接
    const newWs = io(wsserverUrl.value + token, {query: {id: randomId}});
    wsConnections.value.set(token, newWs);
    currentProjectToken.value = token;
    // 提供当前项目的 WebSocket 连接给子组件
    provide(WebSocketSymbol, newWs);
    newWs.connect();

    newWs.on('connect', () => {
      console.log(`Connected to WebSocket for project ${token}`);
      //console.log("Real WS URL:", newWs.io.engine.transport.ws?.url);
      isConnected.value = true;
    });
    newWs.on('disconnect', () => {
      console.log(`Disconnected from WebSocket for project ${token}`);
      //console.log("Real WS URL:", newWs.io.engine.transport.ws?.url);
      isConnected.value = false;
    });
    


    newWs.on('process',(data: any)=>{
      console.log('Project process',data)
    })
    newWs.on('judge', (data: any) => {
      console.log('Received toolExecuteTest:', data)
      messages.value.push({
        id: generateUniqueId(),
        sender: 'Server',
        type: 'functionTest',
        content: data,
        timestamp: Date.now(),
        route: "judge"
      })
    });
    newWs.on('next_chapter', (data: any) => {
      console.log('Received functionCall:', data)
      messages.value.push({
        id: generateUniqueId(),
        sender: 'Server',
        type: 'functionTest',
        content: data,
        timestamp: Date.now(),
        route: "next_chapter"
      })
    });
  };


let currentHandler: ((data: any) => void) | null = null;
const selectMessageRoute=(route:string)=>{
  messageRoute.value = route;
    const ws = getCurrentWs();
  if (!ws) {
    console.error('WebSocket connection is not established');
    return;
  }
  // 移除旧的 handler
  if (currentHandler) {
    ws.off(route, currentHandler);  // 或 ws.removeListener
  }
  currentHandler = (data:any) => {
    console.log('Received data: ', data);

    let sender = "";
    if(data.role == "user"){
      sender = "user";
    }else if(data.role == "assistant"){
      sender = "assistant";
    }else if(data.role == "system"){
      sender = "system";
    }
    // 检查data是不是dict
    let textobj = {};
    if(typeof data.data == "object"){
      textobj = data.data;
    }else{
      textobj = {'text':data.data, 'end':true};
    }
    // 将messages中的sender为user的最后一个message且end为true的message，找到它后的一个为user的message设置其textobj，找不到则添加message
    let hasEnd = false;//是否有已经结束的message
    let seted = false;

    for(let i=messages.value.length - 1; i >= 0; i--){
      if (messages.value[i].sender == sender && messages.value[i].content.data.end == true){
        hasEnd = true;
        break;
      }
      if (messages.value[i].sender == sender && messages.value[i].content.data.end == false){
        messages.value[i].content.data = textobj;
        seted = true;
        break;
      }
    }
    if (seted){
      return;
    }
    if (hasEnd){
      messages.value.push({
        id: generateUniqueId(),
        sender: sender,
        type: 'text',
        content: {data:textobj, role:data.role},
        timestamp: Date.now(),
        route:messageRoute.value
      })
      return;
    }
    
    messages.value.push({
      id: generateUniqueId(),
      sender: sender,
      type: 'text',
      content: {data:textobj,role:data.role},
      timestamp: Date.now(),
      route:messageRoute.value
    })
    
  }
  ws.on(route, currentHandler);
}
const selectAudioRoute=(route:string)=>{
  audioRoute.value =route;
  //startAudioRecording();
}
const selectImageRoute=(route:string)=>{
  imageRoute.value =route;
}
const startAudioRecording = async () => {
  try {
    const stream = await navigator.mediaDevices.getUserMedia({ 
      audio: {
        sampleRate: 16000,
        channelCount: 1,
        echoCancellation: true,
        noiseSuppression: true
      }
    });
    
    const audioContext = new AudioContext({
      sampleRate: 16000
    });
    
    // Load the AudioWorklet
    await audioContext.audioWorklet.addModule('/js/audio-processor.js');
    
    const source = audioContext.createMediaStreamSource(stream);
    const workletNode = new AudioWorkletNode(audioContext, 'audio-processor');
    let audioChunks: Float32Array[] = [];
    
    workletNode.port.onmessage = (e) => {
      audioChunks.push(new Float32Array(e.data));
      
      if (audioChunks.length >= 16) {
        // 合并所有音频块
        const totalLength = audioChunks.reduce((acc, chunk) => acc + chunk.length, 0);
        const mergedData = new Float32Array(totalLength);
        let offset = 0;
        for (const chunk of audioChunks) {
          mergedData.set(chunk, offset);
          offset += chunk.length;
        }
        
        const audioMessage = {
          id: randomId,
          type: 'audio',
          data: mergedData,
          sampleRate: 16000,
          timestamp: Date.now()
        };
        sendAudioDataInRoute(audioRoute.value, audioMessage);
        audioChunks = [];
      }
    };
    
    source.connect(workletNode);
    workletNode.connect(audioContext.destination);
    
    mediaRecorder.value = {
      stop: () => {
        source.disconnect();
        workletNode.disconnect();
        stream.getTracks().forEach(track => track.stop());
        audioContext.close();
      }
    } as MediaRecorder;
    
    isRecording.value = true;
  } catch (error) {
    console.error('Error starting audio recording:', error);
  }
};

const stopAudioRecording = () => {
  if (mediaRecorder.value && isRecording.value) {
    mediaRecorder.value.stop();
    isRecording.value = false;
  }
};

  // 发送消息到当前项目的 WebSocket 服务器
  const sendMessage = (message: any) => {
    const currentWs = getCurrentWs();
    console.log(currentWs)
    console.log(messageRoute)
    if (currentWs && isConnected.value) {
      console.log("messageRoute.value:",messageRoute.value)
      currentWs.emit(messageRoute.value, {id: randomId, ...message});
      console.log('Message sent:', message);
    } else {
      console.error('WebSocket is not connected');
    }
  };

  const sendDataInRoute = (route: string, data: any) => {
    const currentWs = getCurrentWs();
    if (currentWs && isConnected.value) {
      console.log('Sending data to route:', route, data)
      //console.log("route:",route)
      currentWs.emit(route, {id: randomId, ...data});
    }
  }

  const sendAudioDataInRoute = (route: string, data: any) => {
    const currentAudioWs = getCurrentWs();
    if (currentAudioWs ) {
      currentAudioWs.emit(route, {id: randomId, ...data});
    }
  }

  // 关闭指定项目的 WebSocket 连接
  const closeWebSocket = (projectId?: string) => {
    const targetProjectId = projectId || currentProjectToken.value;
    if (targetProjectId) {
      const ws = wsConnections.value.get(targetProjectId);
      if (ws) {
        ws.close();
        wsConnections.value.delete(targetProjectId);
        console.log(`WebSocket connection closed for project ${targetProjectId}`);
      }
    }
  };

  // 切换到另一个项目的 WebSocket 连接
  const switchProject = (projectId: string) => {
    if (wsConnections.value.has(projectId)) {
      currentProjectToken.value = projectId;
      const ws = wsConnections.value.get(projectId);
      if (ws) {
        provide(WebSocketSymbol, ws);
        isConnected.value = ws.connected;
      }
    }
  };
  // const getWsHistory = (route: string, projectId?: string,user_ID?:string,wsToken?:string) => {
  //   postWithCallback('getWsHistory', {
  //     userID: user_ID ? user_ID : userStore.currentUser,
  //     projectID: projectId?projectId:currentProjectToken.value,
  //     wsRoute: wsToken?wsToken:getCurrentWs(),
  //     route: route
  //   }, (res) => {
  //     if (res.success) {
  //       console.log(`Fetch chat history success,route:${route}`,res)
  //     }
  //     else {
  //       console.log(`Fetch chat history failed,route:${route}`,res)
  //     }
  //   })
  // }
  return { 
    serverUrl, 
    get, 
    post, 
    postFile,
    postWithCallback,
    ws: getCurrentWs,
    isConnected,
    messages, 
    connectWebSocket,
    sendMessage, 
    closeWebSocket,
    switchProject,
    currentProjectToken,
    sendDataInRoute,
    sendAudioDataInRoute,
    selectMessageRoute,
    selectAudioRoute,
    startAudioRecording,
    stopAudioRecording,
    isRecording,
    selectImageRoute,
    imageRoute,
    messageRoute
  };
};

function generateUniqueId(): string {
  return Math.random().toString(36).substring(2, 9);
}

export default useServer;